<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>取消请求</title>
	<link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css"
		crossorigin="anonymous">
	<!--<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.7.8/axios.min.js"></script>-->
</head>

<body>
	<div class="container">
		<h2 class="page-header">axios取消请求</h2>
		<button class="btn btn-primary"> 发送请求 </button>
		<button class="btn btn-warning"> 取消请求 </button>
	</div>
	<script>
		// 构造函数
		function Axios(config) {
			this.config = config;
		}
		// 原型 request 方法
		Axios.prototype.request = function (config) {
			return dispatchRequest(config);
		}
		// dispatchRequest 函数
		function dispatchRequest(config) {
			return xhrAdapter(config);
		}
		// xhrAdapter
		function xhrAdapter(config) {
			// 发送 AJAX 请求
			return new Promise((resolve, reject) => {
				// 实例化对象
				const xhr = new XMLHttpRequest();
				// 初始化
				xhr.open(config.method, config.url);
				// 发送
				xhr.send();
				// 处理结果
				xhr.onreadystatechange = function () {
					if (xhr.readyState === 4) {
						// 判断结果
						if (xhr.status >= 200 && xhr.status < 300) {
							// 设置成功的状态
							resolve({
								status: xhr.status,
								statusText: xhr.statusText
							});
						} else {
							reject(new Error('请求失败'));
						}
					}
				}
				// 关于取消请求的处理
				if (config.cancelToken) {
					// 对 cancelToken 对象身上的 promise 对象指定成功的回调
					config.cancelToken.promise.then(value => {
						xhr.abort();
						// 将整体结果设置为失败
						reject(new Error('请求已经被取消'));
					});
				}
			})
		}
		// 创建 axios 函数
		const context = new Axios({});
		const axios = Axios.prototype.request.bind(context);
		//console.dir(axios);

		// CancelToken 构造函数
		function CancelToken(executor) {
			// 声明一个变量
			var resolvePromise;
			// 为实例对象添加属性
			this.promise = new Promise((resolve) => {
				// 将 resolve 赋值给 resolvePromise
				resolvePromise = resolve;
			});
			// 调用 executor 函数
			executor(function () {
				// 执行 resolvePromise 函数
				resolvePromise();
			});
		}


		// 获取按钮  以上为模拟实现的代码
		const btns = document.querySelectorAll('button');
		// 2. 声明全局变量
		let cancel = null

		// 发送请求
		btns[0].onclick = function () {
			// 检测上一次的请求是否已经完成
			if (cancel) {
				// 取消上一次的请求
				cancel();
			}

			// 创建 cancelToken 的值
			let cancelToken = new CancelToken(function (c) {
				// 3. 将 c 的值赋值给 cancel
				cancel = c;
			});

			axios({
				method: 'GET',
				url: 'http://localhost:3000/posts',
				// 1. 添加配置对象的属性
				cancelToken: cancelToken
			}).then(res => {
				console.log(res);
				// 将 cancel 的值初始化
				cancel = null;
			})
		}

		// 绑定第二个事件取消请求
		btns[1].onclick = function () {
			// 2. 调用 cancel 方法
			cancel();
		}
	</script>
</body>

</html>